'''
Created on Apr 26, 2009

@author: tzoght
'''

class InstrumentTransaction(object):
    def __init__(self, transactionDate,settlementDate,type,symbol,equityName,quantity,price,currency,total):
        self.transactionDate = transactionDate
        self.settlementDate = settlementDate
        self.type = type
        self.symbol = symbol
        self.equityName = equityName
        self.quantity = quantity
        self.price = price
        self.currency = currency
        self.total = total

        
class InstrumentHolding(object):
    def __init__(self,symbol,equityName,quantity,averagePrice,total,currency):
        self.symbol = symbol
        self.equityName = equityName
        self.quantity = quantity
        self.averagePrice = averagePrice
        self.total = total
        self.currency = currency
        
    def getTotal(self):
        return (float(averagePrice) * self.quantity)
    
    def toString(self):
        return self.symbol + ' , ' + str(self.quantity) + ' , ' + str(self.averagePrice) + ' , ' + str(self.total) 
        
        
class EquityReport(object):
    def __init__(self,symbol,equityName,startDate,endDate,initialHolding,currency):
        self.symbol = symbol
        self.equityName = equityName
        self.startDate = startDate
        self.endDate = endDate
        self.holding = initialHolding
        self.transactions = []
        self.curency = currency
        self.calculatedCapitalGainLoss = 0.0
        self.calculateddHolding = None
        self.numberOfSharesDisposed = 0
        self.finalProceedsFromDisposition = 0.0
        self.finalAdjustedCostBase = 0.0
        self.init()
        
    def init(self):
        transactionsNum = 0
        proceedsFromDisposition = 0.0
        sharesDisposed = 0
        adjustedCostBase = 0.0
        sharesAcquired = 0
        averageCostPerShare = 0
        for transaction in self.transactions:
            # is it a buy?
            if transaction.type == 'Buy':
                adjustedCostBase += (transaction.total)*(-1)
                sharesAcquired += transaction.quantity
            # is it a sell ?
            if transaction.type == 'Sell':
                proceedsFromDisposition += transaction.total
                sharesDisposed += transaction.quantity * (-1)
        self.numberOfSharesDisposed = sharesDisposed
        # what's the average cost price
        # It depends on initial holding and shares acquired for this interval
        holdingTotal = 0.0
        holdingQuantity = 0
        if self.holding != None:
            holdingQuantity = (self.holding.quantity)
            holdingTotal = (self.holding.total)
        if sharesAcquired != 0 :
            averageCostPerShare = (float(adjustedCostBase) + holdingTotal) / (sharesAcquired + holdingQuantity)
        else:
            # nothing acquired
            if (holdingQuantity != 0):
                averageCostPerShare = float(holdingTotal)/holdingQuantity
            else:
                # nothing held and nothing new acquired
                self.calculatedCapitalGainLoss = 0.0
                self.holding = None
                return
        adjustedCostBase = (sharesDisposed * averageCostPerShare)
        # when we get to this point, there's either initial holding or there was some buy transactions
        # for this period
        if sharesDisposed != 0:
            # there was some shares disposed
            self.calculatedCapitalGainLoss = proceedsFromDisposition - adjustedCostBase
        else:
            self.calculatedCapitalGainLoss = 0.0
        self.finalProceedsFromDisposition = proceedsFromDisposition
        self.finalAdjustedCostBase = adjustedCostBase
        # What's left is holding
        remaining = (holdingQuantity + sharesAcquired) - sharesDisposed
        if ( remaining != 0 ):
            h = InstrumentHolding(self.symbol, self.equityName, remaining,\
                                  averageCostPerShare, remaining * averageCostPerShare, self.curency)
            self.calculateddHolding = h
        else:
            self.calculateddHolding = None
        
    def addTransaction(self,transaction,reInit):
        if (transaction.type == 'Dividend'):
            return
        if (transaction.type == 'Interest'):
            return  
        if (transaction.type == 'Telephone Banking'):
            return 
        if (transaction.symbol == self.symbol):
            if (transaction.transactionDate <= self.endDate) and (transaction.transactionDate >= self.startDate):
                self.transactions.append(transaction) 
        if (reInit):
            self.init()
        
    def addTransactions(self,transactions):
        for transaction in transactions:
            self.addTransaction(transaction,False)
        self.init()
        
    def getDividends(self):
        return 0
    
    def getRealizedCapitalGainsLosses(self):
        return self.calculatedCapitalGainLoss

    def getResultingHoldings(self):
        return self.calculateddHolding
    
    def isEmpty(self):
        return ((self.holding == None) and (len(self.transactions))== 0)
    
    def toString(self):
        partOne = str(self.numberOfSharesDisposed) + ' , ' + self.symbol + ' ,' \
        + str(self.finalProceedsFromDisposition) + ' , ' + str(self.finalAdjustedCostBase) \
        + ' , ' + str(self.getRealizedCapitalGainsLosses())
        if self.calculateddHolding == None:
            return partOne 
        else:
            return partOne + ' === ' + self.calculateddHolding.toString()
